package lt.marsrutai.mobile.android.fragment;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import lt.marsrutai.mobile.android.AppContext;
import lt.marsrutai.mobile.android.R;
import lt.marsrutai.mobile.android.activity.intent.StopsIntentHolder;
import lt.marsrutai.mobile.android.adapter.TrackBookmarkAdapter;
import lt.marsrutai.mobile.android.exception.DataAccessException;
import lt.marsrutai.mobile.android.exception.UnableAccessDataException;
import lt.marsrutai.mobile.android.manager.ActivityManager;
import lt.marsrutai.mobile.android.model.MobileScope;
import lt.marsrutai.mobile.android.model.Schedule;
import lt.marsrutai.mobile.android.model.Track;
import lt.marsrutai.mobile.android.model.TrackBookmark;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.TextView;

import com.actionbarsherlock.app.SherlockListFragment;

public class TrackBookmarksFragment extends SherlockListFragment {

    private static final Logger logger = LoggerFactory.getLogger("TrackBookmarksFragment");

    private ActivityManager manager;

    private List<TrackBookmark> trackBookmarks;

    private Map<TrackBookmark, MobileScope> mobileScopes;
    private Map<TrackBookmark, Track> tracks;
    private Map<TrackBookmark, Schedule> schedules;

    private TrackBookmarkAdapter adapter;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.list_fragment, null);
        ((TextView) view.findViewById(android.R.id.empty)).setText(R.string.track_bookmarks_not_found);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        registerForContextMenu(getListView());
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if (manager == null) {
            manager = new ActivityManager(getActivity());
        }

        if (null == adapter) {
            downloadData();
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        sendTrackData(trackBookmarks.get(position));
    }

    public void downloadData() {
        Runnable downloadTask = new Runnable() {

            @Override
            public void run() {
                getBookmarkedTracks();
            }
        };
        Thread thread = new Thread(downloadTask);
        thread.start();

        manager.showDownloadLoadingBar();
    }

    private void getBookmarkedTracks() {
        try {
            Set<TrackBookmark> storedTrackBookmarks = AppContext.getBookmarkService().getTrackBookmarks();
            int storedBookmarksCount = storedTrackBookmarks.size();

            trackBookmarks = new ArrayList<TrackBookmark>(storedBookmarksCount);

            // consider default hashmap load factor
            int hashMapSize = (int) (storedBookmarksCount / 0.75);

            mobileScopes = new HashMap<TrackBookmark, MobileScope>(hashMapSize);
            tracks = new HashMap<TrackBookmark, Track>(hashMapSize);
            schedules = new HashMap<TrackBookmark, Schedule>(hashMapSize);

            for (TrackBookmark trackBookmark : storedTrackBookmarks) {
                try {
                    MobileScope mobileScope = AppContext.getDataService().getScopeInfo(trackBookmark.getScope());
                    Track track = AppContext.getDataService().getTrackById(trackBookmark.getScope(),
                            trackBookmark.getTrackId());
                    Schedule schedule = AppContext.getDataService().getScheduleById(trackBookmark.getScope(),
                            track.getScheduleId());

                    mobileScopes.put(trackBookmark, mobileScope);
                    tracks.put(trackBookmark, track);
                    schedules.put(trackBookmark, schedule);
                    trackBookmarks.add(trackBookmark);
                }
                catch (UnableAccessDataException ex) {
                    logger.info(String.format("Unable to access data for scope: %s, trackId: %s.",
                            trackBookmark.getScope(), trackBookmark.getTrackId()));
                    // TODO: delete invalid bookmarks,
                    // ex. tracks that no longer exist
                }
            }
        }
        catch (DataAccessException e) {
            manager.runOnUiThread(manager.errorRes);
            return;
        }
        manager.runOnUiThread(returnRes);
    }

    private Runnable returnRes = new Runnable() {

        @Override
        public void run() {

            adapter = new TrackBookmarkAdapter(getActivity(), tracks, schedules);
            setListAdapter(adapter);

            if (trackBookmarks != null && trackBookmarks.size() > 0) {
                for (int i = 0; i < trackBookmarks.size(); i++) {
                    adapter.add(trackBookmarks.get(i));
                }
            }
            manager.dismissDownloadLoadingBar();
        }
    };

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getActivity().getMenuInflater();
        inflater.inflate(R.menu.track_bookmark_context_menu, menu);
    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        // full class path so it does not get confused with actionbarsherlock class
        android.widget.AdapterView.AdapterContextMenuInfo info = (android.widget.AdapterView.AdapterContextMenuInfo) item
                .getMenuInfo();

        switch (item.getItemId()) {
        case R.id.remove_bookmark:
            TrackBookmark trackBookmark = trackBookmarks.get((int) info.id);
            AppContext.getBookmarkService().removeTrackBookmark(trackBookmark);
            adapter.remove(trackBookmark);
            return true;
        default:
            return super.onContextItemSelected(item);
        }
    }

    public void sendTrackData(TrackBookmark trackBookmark) {
        MobileScope mobileScope = mobileScopes.get(trackBookmark);
        Track track = tracks.get(trackBookmark);
        Schedule schedule = schedules.get(trackBookmark);

        StopsIntentHolder intentHolder = new StopsIntentHolder(getActivity(),
            mobileScope.getFolder(),
            mobileScope.getName(),
            schedule.getTransportId(),
            track.getScheduleId(),
            schedule.getName(),
            schedule.getTrackName(),
            track.getId(),
            track.getName()
        );
        startActivity(intentHolder.getIntent());
    }

}
